home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 1 / PC Actual CD 01.iso / f1 / cimb.arj / BMP.C next >
Encoding:
C/C++ Source or Header  |  1994-09-03  |  10.4 KB  |  473 lines

  1. /*==============================================================================
  2.  
  3. FICHERO: BMP.C
  4.  
  5. AUTOR: ANTONIO LADESA JURADO
  6.  
  7. FECHA: 24/6/94
  8.  
  9. DESCRIPCION:
  10.  
  11.     Fichero que contiene las estructuras, constantes, variables y funciones
  12.     internas y externas para el procesamiento de ficheros BMP.
  13.  
  14. ==============================================================================*/
  15.  
  16.  
  17. /*---- MODULOS USADOS --------------------------------------------------------*/
  18.  
  19. #include <stdio.h>
  20. #include <alloc.h>
  21. #include <string.h>
  22.  
  23. #include "global.h"
  24. #include "memoria.h"
  25. #include "video.h"
  26. #include "bmp.h"
  27. #include "error.h"
  28.  
  29.  
  30. /*---- ESTRUCTURAS, CONSTANTES Y VARIABLES LOCALES AL MODULO -----------------*/
  31.  
  32.  
  33.     /* cabecera de un fichero BMP */
  34. typedef struct
  35. {
  36. char tipo[2];
  37. long longitud;
  38. int reservados[2];
  39. long inicio;
  40. long tam;
  41. long ancho;
  42. long alto;
  43. int planos;
  44. int bitspixel;
  45. long compresion;
  46. long tamimagen;
  47. long x;
  48. long y;
  49. long colores;
  50. long usados;
  51. }CABbmp;
  52.  
  53.     /* cabecera del fichero BMP */
  54. static CABbmp cabecera;
  55.  
  56.  
  57. /*---- DEFINICION DE LAS FUNCIONES INTERNAS ----------------------------------*/
  58.  
  59. IMAGEN *BMPleerCabecera(IMAGEN *c,FILE *f,char *nombre);
  60. IMAGEN *BMPleerImagen(IMAGEN *c,FILE *f);
  61. void BMPleerLinea(char *p, FILE *f,int bytes);
  62.  
  63. void BMPescribirImagen(IMAGEN *c,FILE *f);
  64. void BMPescribirLinea(char *p, FILE *f,int bytes);
  65. void BMPcrearCabecera(IMAGEN *c);
  66.  
  67. /*---- CODIFICACION DE LAS FUNCIONES OFRECIDAS -------------------------------*/
  68.  
  69.  
  70. /*---- FUNCION: extern IMAGEN *BMPcargar(char *nombre,IMAGEN *c) ---------------
  71.  
  72.     Descripción:
  73.  
  74.         Esta función carga en memoria una imagen de tipo BMP.
  75.  
  76.     Parámetros:
  77.  
  78.         char *nombre : nombre del fichero a cargar
  79.         IMAGEN *c : puntero a estructura que alberga la imagen
  80.  
  81.     Retorno:
  82.  
  83.         Puntero a la estructura de la imagen o NULL si hubo error
  84.  
  85. ---- CODIGO: -----------------------------------------------------------------*/
  86.  
  87. extern IMAGEN *BMPcargar(char *nombre,IMAGEN *c)
  88. {
  89. FILE *f;
  90.  
  91.     /* abrir el fichero */
  92. if((f = fopen(nombre, "rb")) != NULL)
  93.     {
  94.         /* leer cabecera BMP */
  95.     if((c = BMPleerCabecera(c,f,nombre))!=NULL)
  96.             /* leer imagen */
  97.         c = BMPleerImagen(c,f);
  98.     fclose(f);
  99.     }
  100. else
  101.     {
  102.     ERRORponer(ERRapertura);
  103.     return(NULL);
  104.     }
  105. return(c);
  106. }
  107.  
  108. /*---- FIN FUNCION -----------------------------------------------------------*/
  109.  
  110.  
  111. /*---- FUNCION: extern int *BMPsalvar(char *nombre,IMAGEN *c) ------------------
  112.  
  113.     Descripción:
  114.  
  115.         Esta función salva en disco una imagen con formato BMP.
  116.  
  117.     Parámetros:
  118.  
  119.         char *nombre : nombre del fichero a salvar
  120.         IMAGEN *c : puntero a estructura que alberga la imagen
  121.  
  122.     Retorno:
  123.  
  124.         - 0 si hay error
  125.         - 1 en caso contrario
  126.  
  127. ---- CODIGO: -----------------------------------------------------------------*/
  128.  
  129.     /* salvar un fichero BMP */
  130. extern int BMPsalvar(char *nombre,IMAGEN *c)
  131. {
  132.     /* puntero al fichero */
  133. FILE *f;
  134.     /* contador */
  135. int i;
  136.     /* puntero auxiliar a paleta */
  137. char *paux;
  138.  
  139.     /* abrir el fichero */
  140. if((f = fopen(nombre, "wb")) == NULL)
  141.     {
  142.     ERRORponer(ERRapertura);
  143.     return(0);
  144.     }
  145.  
  146.     /* crear la cabecera BMP */
  147. BMPcrearCabecera(c);
  148.  
  149.     /* escribir la cabecera BMP */
  150. if(fwrite((char *)&cabecera,1,sizeof(CABbmp),f) != sizeof(CABbmp))
  151.     {
  152.     ERRORponer(ERRescritura);
  153.     fclose(f);
  154.     return(0);
  155.     }
  156.  
  157.     /* escribir paleta BMP */
  158. for(i=0,paux = c->paleta;i<c->colores;++i,paux+=3)
  159.             {
  160.                 /* la paleta BMP está en formato BGRI */
  161.                 /* invertir RGB -> BGR */
  162.             fputc(*(paux+2),f);
  163.             fputc(*(paux+1),f);
  164.             fputc(*paux,f);
  165.             fputc(0,f);
  166.             }
  167.     /* escribir la imagen BMP */
  168. BMPescribirImagen(c,f);
  169. fclose(f);
  170. return(1);
  171. }
  172.  
  173. /*---- FIN FUNCION -----------------------------------------------------------*/
  174.  
  175.  
  176. /*---- CODIFICACION DE LAS FUNCIONES INTERNAS --------------------------------*/
  177.  
  178.  
  179. /*---- FUNCION: IMAGEN *BMPleerCabecera(IMAGEN *c,FILE *f,char *nombre) --------
  180.  
  181.     Descripción:
  182.  
  183.         Esta función reserva memoria para la imagen y lee la cabecera del fichero
  184.         BMP.
  185.  
  186.     Parámetros:
  187.  
  188.  
  189.         IMAGEN *c : puntero a estructura que alberga la imagen
  190.         FILE *f : puntero al fichero
  191.         char *nombre : nombre del fichero a cargar
  192.  
  193.     Retorno:
  194.  
  195.         Puntero a la estructura de la imagen o NULL si hubo error
  196.  
  197. ---- CODIGO: -----------------------------------------------------------------*/
  198.  
  199. IMAGEN *BMPleerCabecera(IMAGEN *c,FILE *f,char *nombre)
  200. {
  201. int i;
  202. char *paux;
  203.  
  204.     /* lectura de la cabecera */
  205. if(fread((char *)&cabecera,1,sizeof(CABbmp),f) == sizeof(CABbmp))
  206.     {
  207.         /* comprobar que es BMP */
  208.     if(memcmp(cabecera.tipo,"BM",2) || cabecera.planos != 1
  209.                                                                     || cabecera.compresion)
  210.         {
  211.         ERRORponer(ERRnoTratado);
  212.         return(NULL);
  213.         }
  214.     }
  215. else
  216.     {
  217.     ERRORponer(ERRlectura);
  218.     return(NULL);
  219.     }
  220.  
  221.     /* reservar memoria para la cabecera de trabajo */
  222. if((c=MEMreservarCAB(c))==NULL)
  223.     {
  224.     ERRORponer(ERRnoMemoria);
  225.     return(NULL);
  226.     }
  227.  
  228.     /* cargar cabecera de trabajo */
  229. strcpy(c->nombre,nombre);
  230. c->ancho= (int)cabecera.ancho;
  231. c->alto = (int)cabecera.alto;
  232. c->formato = BMP;
  233.     /* determinar tipo de imagen */
  234. switch(cabecera.bitspixel)
  235.     {
  236.         /* monocromática */
  237.     case 1:
  238.         c->modo = VIDEOmono;
  239.         c->bytes = DePixelsABytes(c->ancho);
  240.         c->colores = 2;
  241.         c->haypaleta = FALSO;
  242.     break;
  243.  
  244.         /* 16 colores, se guarda como VGA */
  245.     case 4:
  246.         c->modo = VIDEOvga;
  247.         c->bytes = c->ancho;
  248.         c->colores = 16;
  249.         c->haypaleta = CIERTO;
  250.     break;
  251.  
  252.         /* 256 colores */
  253.     case 8:
  254.         c->modo = VIDEOvga;
  255.         c->bytes = c->ancho;
  256.         c->colores = 256;
  257.         c->haypaleta = CIERTO;
  258.     break;
  259.  
  260.         /* formato desconocido */
  261.     default:
  262.         ERRORponer(ERRnoTratado);
  263.         c = MEMliberar(c);
  264.         return(NULL);
  265.     }
  266.  
  267.     /* si existe paleta, cargarla */
  268. if(cabecera.colores == 0 && cabecera.bitspixel != 1)
  269.     {
  270.     for(i=0,paux = c->paleta;i<c->colores;++i,paux+=3)
  271.         {
  272.             /* la paleta tiene 4 componentes: BGRI */
  273.         fread((char *)paux,3,1,f);
  274.             /* el cuarto se desecha */
  275.         fgetc(f);
  276.         }
  277.         /* la paleta viene invertida (RGB <-> BGR) */
  278.     memcpy(c->paleta,VIDEOinvertirPaleta(c->paleta,c->colores),c->colores*3);
  279.     }
  280.  
  281.     /* si no hay memoria para la imagen, liberar cabecera */
  282. if(!MEMreservar(c))
  283.     {
  284.     c =MEMliberar(c);
  285.     ERRORponer(ERRnoMemoria);
  286.     return(c);
  287.     }
  288. return(c);
  289. }
  290.  
  291. /*---- FIN FUNCION -----------------------------------------------------------*/
  292.  
  293.  
  294. /*---- FUNCION: IMAGEN *BMPleerImagen(IMAGEN *c,FILE *f) -----------------------
  295.  
  296.     Descripción:
  297.  
  298.         Esta función carga en memoria una imagen de tipo BMP.
  299.  
  300.     Parámetros:
  301.  
  302.  
  303.         IMAGEN *c : puntero a estructura que alberga la imagen
  304.         FILE *f : puntero al fichero
  305.  
  306.     Retorno:
  307.  
  308.         Puntero a la estructura de la imagen
  309.  
  310. ---- CODIGO: -----------------------------------------------------------------*/
  311.  
  312. IMAGEN *BMPleerImagen(IMAGEN *c,FILE *f)
  313. {
  314.     /* contadores */
  315. int i,j,n;
  316.     /* buffers */
  317. char p[1024];
  318. char q[1024];
  319.  
  320.     /* posicionar puntero al inicio de la imagen */
  321. fseek(f,cabecera.inicio,SEEK_SET);
  322.  
  323.     /* cargar imagen */
  324. for(i = c->alto-1; i >= 0;--i)
  325.     {
  326.         /* si es de 16 colores, de cada byte se extraen 2 pixels */
  327.     if( cabecera.bitspixel == 4)
  328.         {
  329.     BMPleerLinea(p,f,c->bytes/2);
  330.         for(j=0,n=0;j<c->bytes/2;j++,n+=2)
  331.             {
  332.             q[n+1] = p[j] & 0x0f;
  333.             q[n] = (p[j] & 0xf0) >> 4;
  334.             }
  335.         MEMescribir(q,i,c);
  336.         }
  337.     else
  338.         {
  339.             /* si es monocroma o vga, se lee normalmente */
  340.         BMPleerLinea(p,f,c->bytes);
  341.         MEMescribir(p,i,c);
  342.         }
  343.     }
  344. return(c);
  345. }
  346.  
  347. /*---- FIN FUNCION -----------------------------------------------------------*/
  348.  
  349.  
  350. /*---- FUNCION: void BMPleerLinea(char *p, FILE *f,int bytes) ------------------
  351.  
  352.     Descripción:
  353.  
  354.         Esta función lee una línea de un fichero BMP.
  355.  
  356.     Parámetros:
  357.  
  358.         char *p : puntero a buffer donde se almacena la línea
  359.         FILE *f : puntero al fichero
  360.         int bytes: numero de bytes por linea
  361.  
  362. ---- CODIGO: -----------------------------------------------------------------*/
  363.  
  364. void BMPleerLinea(char *p, FILE *f,int bytes)
  365. {
  366. fread(p,bytes,1,f);
  367. }
  368.  
  369. /*---- FIN FUNCION -----------------------------------------------------------*/
  370.  
  371.  
  372. /*---- FUNCION: void BMPcrearCabecera(IMAGEN *c) -------------------------------
  373.  
  374.     Descripción:
  375.  
  376.         Esta función crea una cabecera BMP.
  377.  
  378.     Parámetros:
  379.  
  380.         IMAGEN *c : puntero a estructura que alberga la imagen
  381.  
  382. ---- CODIGO: -----------------------------------------------------------------*/
  383.  
  384. void BMPcrearCabecera(IMAGEN *c)
  385. {
  386.     /* relleno de la cabecera */
  387. strcpy(cabecera.tipo,"BM");
  388. cabecera.reservados[0] = cabecera.reservados[1] = 0;
  389. cabecera.inicio = sizeof(CABbmp) + (c->colores * 4);
  390. cabecera.tam = 40;
  391. cabecera.ancho = c->ancho;
  392. cabecera.alto = c->alto;
  393. cabecera.planos = 1;
  394. cabecera.longitud = cabecera.inicio + (c->alto * c->bytes);
  395. switch(c->modo)
  396.     {
  397.     case VIDEOmono:cabecera.bitspixel = 1;break;
  398.     case VIDEOega:cabecera.bitspixel = 4;break;
  399.     case VIDEOvga:cabecera.bitspixel = 8;break;
  400.     };
  401. cabecera.compresion = cabecera.tamimagen = cabecera.x = cabecera.y =
  402. cabecera.colores = cabecera.usados = 0;
  403. }
  404.  
  405. /*---- FIN FUNCION -----------------------------------------------------------*/
  406.  
  407.  
  408. /*---- FUNCION: void BMPescribirImagen(IMAGEN *c,FILE *f) ----------------------
  409.  
  410.     Descripción:
  411.  
  412.         Esta función graba la imagen en un fichero BMP.
  413.  
  414.     Parámetros:
  415.  
  416.         IMAGEN *c : puntero a estructura que alberga la imagen
  417.         FILE *f : puntero al fichero
  418.  
  419. ---- CODIGO: -----------------------------------------------------------------*/
  420.  
  421. void BMPescribirImagen(IMAGEN *c,FILE *f)
  422. {
  423.     /* contador de líneas */
  424. int i;
  425.     /* buffers */
  426. char p[1024];
  427. char q[1024];
  428.  
  429.     /* salvar imagen */
  430. for(i = c->alto-1; i >= 0;--i)
  431.     {
  432.         /* si el modo es ega, convertir los bits de plano a pixel */
  433.     if(c->modo == VIDEOega)
  434.         {
  435.         MEMleer(q,i,c);
  436.         EGAdePlanoaPixel(q,p,c->ancho);
  437.         BMPescribirLinea(p,f,c->bytes);
  438.         }
  439.     else
  440.         {
  441.         MEMleer(p,i,c);
  442.         BMPescribirLinea(p,f,c->bytes);
  443.         }
  444.     }
  445. }
  446.  
  447. /*---- FIN FUNCION -----------------------------------------------------------*/
  448.  
  449.  
  450. /*---- FUNCION: void BMPescribirLinea(char *p, FILE *f,int bytes) --------------
  451.  
  452.     Descripción:
  453.  
  454.         Esta función escribe una línea en un fichero BMP.
  455.  
  456.     Parámetros:
  457.  
  458.         char *p : puntero a buffer que alberga la línea
  459.         FILE *f : puntero al fichero
  460.         int bytes : numero de bytes por línea
  461.  
  462.     Retorno:
  463.  
  464.         Puntero a la estructura de la imagen o NULL si hubo error
  465.  
  466. ---- CODIGO: -----------------------------------------------------------------*/
  467.  
  468. void BMPescribirLinea(char *p, FILE *f,int bytes)
  469. {
  470. fwrite(p,bytes,1,f);
  471. }
  472.  
  473. /*---- FIN FUNCION -----------------------------------------------------------*/